import eventBus, {Events} from '@/event-bus';
import type {Point} from '@/types';
import {useCanvasStore} from '@/store/modules/canvas';
import {useBlocksStore} from '@/store/modules/blocks';
import {useToolsStore} from '@/store/modules/tools';
import {draw2Real, real2Draw} from '@/utils/coordTransform';
import {drawGrid, drawBlock, drawSelectedBlock} from './drawHelpers';
import {pointInRotatedRect} from '@/utils/collisionDetection';

export class CanvasEngine {
    private canvas: HTMLCanvasElement;
    private ctx: CanvasRenderingContext2D;
    private container: HTMLElement;

    // 状态管理
    private canvasStore = useCanvasStore();
    private blocksStore = useBlocksStore();
    private toolsStore = useToolsStore();

    // 交互状态
    private isDragging = false;
    private dragStart: Point = {x: 0, y: 0};
    private dragOffset: Point = {x: 0, y: 0};
    private draggingBlockId: string | null = null;

    constructor(containerId: string) {
        // 获取容器元素
        const container = document.getElementById(containerId);
        if (!container) {
            throw new Error(`Canvas container with id "${containerId}" not found`);
        }
        this.container = container;

        // 创建画布元素
        this.canvas = this.createCanvas();
        this.ctx = this.canvas.getContext('2d')!;

        // 初始化事件监听
        this.initEventListeners();

        // 初始化画布尺寸
        this.resizeCanvas();
    }

    /**
     * 创建画布元素
     */
    private createCanvas(): HTMLCanvasElement {
        const canvas = document.createElement('canvas');
        canvas.style.display = 'block';
        canvas.style.backgroundColor = this.canvasStore.backgroundColor;
        this.container.appendChild(canvas);
        return canvas;
    }

    /**
     * 初始化事件监听
     */
    private initEventListeners() {
        // 窗口大小变化时调整画布尺寸
        window.addEventListener('resize', () => this.resizeCanvas());

        // 画布鼠标事件
        this.canvas.addEventListener('mousedown', (e) => this.handleMouseDown(e));
        this.canvas.addEventListener('mousemove', (e) => this.handleMouseMove(e));
        this.canvas.addEventListener('mouseup', () => this.handleMouseUp());
        this.canvas.addEventListener('mouseleave', () => this.handleMouseUp());

        // 鼠标滚轮事件（缩放）
        this.canvas.addEventListener('wheel', (e) => this.handleWheel(e));

        // 事件总线监听
        eventBus.on(Events.CANVAS_REFRESH, () => this.render());
        eventBus.on(Events.BLOCK_ADDED, () => this.render());
        eventBus.on(Events.BLOCK_DELETED, () => this.render());
        eventBus.on(Events.BLOCK_UPDATED, () => this.render());
        eventBus.on(Events.BLOCK_SELECTED, () => this.render());
        eventBus.on(Events.SCALE_CHANGED, () => this.render());
        eventBus.on(Events.SCENE_LOADED, () => this.render());
        eventBus.on(Events.SCENE_CLEARED, () => this.render());
    }

    /**
     * 调整画布尺寸
     */
    private resizeCanvas() {
        // 设置画布尺寸为容器尺寸
        const {width, height} = this.container.getBoundingClientRect();
        this.canvas.width = width;
        this.canvas.height = height;

        // 更新画布状态
        this.canvasStore.setSize(width, height);

        // 重新渲染
        this.render();
    }

    /**
     * 处理鼠标按下事件
     */
    private handleMouseDown(event: MouseEvent) {
        const {offsetX: x, offsetY: y} = event;
        const realPos = draw2Real(this.canvasStore.scale, this.canvasStore.origin, {x, y});

        // 根据当前工具处理不同行为
        const activeTool = this.toolsStore.activeToolKey;

        switch (activeTool) {
            case 'select':
                this.handleSelectToolDown({x, y}, realPos);
                break;

            case 'delete':
                this.handleDeleteToolDown(realPos);
                break;

            case 'add-car':
            case 'add-flatcar':
            case 'add-pedestrian':
            case 'add-bicycle':
                this.handleAddToolDown(activeTool, realPos);
                break;
        }

        // 发出画布点击事件
        eventBus.emit(Events.CANVAS_CLICKED, realPos);
    }

    /**
     * 处理选择工具的鼠标按下
     */
    private handleSelectToolDown(drawPos: Point, realPos: Point) {
        // 检查是否点击了某个块
        const clickedBlock = this.blocksStore.blocks.find(block => {
            return pointInRotatedRect(
                realPos,
                {x: block.x, y: block.y},
                block.collision.l1,
                block.collision.l2,
                block.heading
            );
        });

        if (clickedBlock) {
            // 选中块并准备拖动
            this.blocksStore.selectBlock(clickedBlock.id);
            this.draggingBlockId = clickedBlock.id;
            this.isDragging = true;
            this.dragStart = drawPos;

            // 计算拖动偏移量（块中心到点击位置）
            const blockDrawPos = real2Draw(
                this.canvasStore.scale,
                this.canvasStore.origin,
                {x: clickedBlock.x, y: clickedBlock.y}
            );

            this.dragOffset = {
                x: drawPos.x - blockDrawPos.x,
                y: drawPos.y - blockDrawPos.y
            };
        } else {
            // 未点击块，开始平移画布
            this.blocksStore.selectBlock(null);
            this.isDragging = true;
            this.dragStart = drawPos;
            this.draggingBlockId = null;
        }
    }

    /**
     * 处理删除工具的鼠标按下
     */
    private handleDeleteToolDown(realPos: Point) {
        // 检查是否点击了某个块
        const clickedBlock = this.blocksStore.blocks.find(block => {
            return pointInRotatedRect(
                realPos,
                {x: block.x, y: block.y},
                block.collision.l1,
                block.collision.l2,
                block.heading
            );
        });

        if (clickedBlock) {
            this.blocksStore.deleteBlock(clickedBlock.id);
        }
    }

    /**
     * 处理添加工具的鼠标按下
     */
    private handleAddToolDown(toolKey: string, realPos: Point) {
        // 从工具key中提取类型（如"add-car" -> "car"）
        const type = toolKey.split('-')[1] as any;
        this.blocksStore.addBlock(type, realPos);
    }

    /**
     * 处理鼠标移动事件
     */
    private handleMouseMove(event: MouseEvent) {
        if (!this.isDragging) return;

        const {offsetX: x, offsetY: y} = event;

        if (this.draggingBlockId) {
            // 拖动块
            const blockDrawPos = {
                x: x - this.dragOffset.x,
                y: y - this.dragOffset.y
            };

            const blockRealPos = draw2Real(
                this.canvasStore.scale,
                this.canvasStore.origin,
                blockDrawPos
            );

            this.blocksStore.updateBlock(this.draggingBlockId, {
                x: parseFloat(blockRealPos.x.toFixed(3)),
                y: parseFloat(blockRealPos.y.toFixed(3))
            });
        } else {
            // 平移画布
            const delta = {
                x: x - this.dragStart.x,
                y: y - this.dragStart.y
            };

            this.canvasStore.pan(delta);
            this.dragStart = {x, y};
        }
    }

    /**
     * 处理鼠标释放事件
     */
    private handleMouseUp() {
        this.isDragging = false;
        this.draggingBlockId = null;
    }

    /**
     * 处理鼠标滚轮事件（缩放）
     */
    private handleWheel(event: WheelEvent) {
        event.preventDefault();
        // 计算缩放因子（向上滚动放大，向下滚动缩小）
        const factor = event.deltaY < 0 ? 1.01 : 0.99;

        // 获取鼠标在画布上的位置
        const rect = this.canvas.getBoundingClientRect();
        const mousePos = {
            x: event.clientX - rect.left,
            y: event.clientY - rect.top
        };

        // 应用缩放
        this.canvasStore.zoom(factor, mousePos);
    }

    /**
     * 渲染画布
     */
    public render() {
        // 清除画布
        this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);

        // 绘制网格（如果启用）
        if (this.canvasStore.showGrid) {
            drawGrid(this.ctx, this.canvas, this.canvasStore);
        }

        // 绘制所有块
        this.blocksStore.blocks.forEach(block => {
            drawBlock(this.ctx, block, this.canvasStore);
        });

        // 绘制选中块的高亮效果
        if (this.blocksStore.selectedBlock) {
            drawSelectedBlock(this.ctx, this.blocksStore.selectedBlock, this.canvasStore);
        }
    }

    /**
     * 销毁画布引擎
     */
    public destroy() {
        // 移除事件监听
        window.removeEventListener('resize', () => this.resizeCanvas());

        // 移除画布元素
        if (this.canvas.parentNode === this.container) {
            this.container.removeChild(this.canvas);
        }
    }
}
